/*
 * @Description: 页面加载loading（顶部加载进度loading、全屏遮罩）
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-09-08 14:29:46
 * @LastEditTime: 2023-03-29 09:59:47
 */

interface IcssOptions {
  color?: string; //进度条颜色
  duration1?: number; //第1阶段持续时间，单位毫秒
  duration2?: number; //第2阶段持续时间
}

class PageLoading {
  static instance?: PageLoading;
  isShow: boolean = false;
  index: number = 0;

  private loadingEl: HTMLDivElement;
  private styleEl: HTMLStyleElement;
  private options: IcssOptions;

  constructor(options?: IcssOptions) {
    const {
      color = "#409eff",
      duration1 = 5000,
      duration2 = 300,
    } = options || {};

    this.options = { color, duration1, duration2 };

    this.loadingEl = document.createElement("div");
    this.loadingEl.setAttribute("data-type", "pageLoading");
    this.loadingEl.className = "gxh-page-loading-mask";
    this.loadingEl.innerHTML =
      '<div class="gxh-page-loading-progress"></div><div class="gxh-page-loading-icon"><svg class="circular" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none"></circle></svg></div>';

    this.styleEl = document.createElement("style");
    this.styleEl.setAttribute("type", "text/css");
    this.styleEl.setAttribute("data-type", "pageLoading");
    this.styleEl.innerText = this.getCss(this.options);
  }

  // 单例
  static getInstance(options?: IcssOptions) {
    if (!this.instance) {
      this.instance = new PageLoading(options);
    }
    return this.instance;
  }

  show() {
    this.index++;
    if (this.isShow) {
      return;
    }
    this.isShow = true;
    this.loadingEl.className = "gxh-page-loading-mask";
    document.head.append(this.styleEl);
    document.body.append(this.loadingEl);
    // nextTick
    setTimeout(
      () => (this.loadingEl.className = "gxh-page-loading-mask gxh-pl-start")
    );
  }

  hide() {
    if (!this.isShow) {
      throw new Error("PageLoading的hide方法必须与show方法连用！");
    }

    // 为了避免在关闭时还有未完成的loading，每关一次index减一，直到为0
    this.index--;

    if (this.index !== 0) {
      return;
    }

    this.loadingEl.className = "gxh-page-loading-mask gxh-pl-finish";
    const t = setTimeout(() => {
      document.body.removeChild(this.loadingEl);
      document.head.removeChild(this.styleEl);
      this.isShow = false;
      clearTimeout(t);
    }, this.options.duration2);
  }

  private getCss(options: IcssOptions): string {
    const { color, duration1, duration2 } = options;
    return `
            @keyframes=gxh-page-loading-anim{
                100% {
                    transform: rotate(360deg);
                }
            }
            @keyframes=gxh-page-loading-dash{
                0% {
                    stroke-dasharray: 1,200;
                    stroke-dashoffset: 0;
                }
                50% {
                    stroke-dasharray: 90,150;
                    stroke-dashoffset: -40px;
                }
                100% {
                    stroke-dasharray: 90,150;
                    stroke-dashoffset: -120px;
                }
            }
            .gxh-page-loading-mask{
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                z-index: 9999;
                cursor: progress;
            }
            .gxh-page-loading-progress{
                position: absolute;
                width: 0;
                height: 2px;
                background:${color};
                transition-property:width;
            }
            .gxh-page-loading-icon {
                position: absolute;
                right: 1px;
                top: 1px;
            }
            .gxh-page-loading-icon>svg.circular {
                height: 20px;
                width: 20px;
                animation: gxh-page-loading-anim=2s=linear=infinite;
            }
            .gxh-page-loading-icon>svg.circular>circle.path {
                animation: gxh-page-loading-dash=1.5s=ease-in-out=infinite;
                stroke-dasharray: 90,150;
                stroke-dashoffset: 0;
                stroke-width: 4px;
                stroke: ${color};
                stroke-linecap: round;
            }
            .gxh-pl-start>.gxh-page-loading-progress{
                transition-duration: ${duration1}ms;
                width: 80%;
            }
            .gxh-pl-finish>.gxh-page-loading-progress{
                transition-duration: ${duration2}ms;
                width: 100%;
            }
        `.replace(/\s|=/g, (e) => {
      return e === "=" ? " " : "";
    });
  }
}

// 这里导出一个实例对象。同一个页面不同组件导入的是同一个实例，实例中的变量会共享
// 但为了避免出现多个实例，也可导出一个class类，然后在项目中存一个全局变量
// export default PageLoading
export default PageLoading.getInstance();
